#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

void priStr(unsigned char* buf, int len) {
	int i; 
	printf("\n");
	for (i = 0; i < len; i++) {
		if (((i+1) % 20) == 0) printf("\n");
		//printf("0x[%02x]", buf[i]);
		//printf("[%02x]", buf[i]);
		printf("%c", buf[i]);
	}
	printf("\n");
}
const char base[] = "WXYZabcde5KLMNHIJ1STUVB789]vwxyCDfghi[As234EFopqrOPz0QRtujklmn6G-";
static char find_pos(char ch)   { 
	char *ptr = (char*)strrchr(base, ch);
	return (ptr - base); 
} 

static char *base64_encode(const char* data, int data_len) { 
	int prepare = 0; 
	int ret_len; 
	int temp = 0; 
	char *ret = NULL; 
	char *f = NULL; 
	int tmp = 0; 
	char changed[4]; 
	int i = 0; 
	ret_len = data_len / 3; 
	temp = data_len % 3; 
	if (temp > 0) { 
		ret_len += 1; 
	} 
	ret_len = ret_len*4 + 1; 
	ret = (char *)malloc(ret_len); 

	if ( ret == NULL) { 
		printf("No enough memory.\n"); 
		exit(0); 
	} 
	memset(ret, 0, ret_len); 
	f = ret; 
	while (tmp < data_len) { 
		temp = 0; 
		prepare = 0; 
		memset(changed, '\0', 4); 
		while (temp < 3) { 
			if (tmp >= data_len) { break; } 
			prepare = ((prepare << 8) | (data[tmp] & 0xFF)); 
			tmp++; 
			temp++; 
		} 
		prepare = (prepare<<((3-temp)*8)); 

		for (i = 0; i < 4 ;i++ ) { 
			if (temp < i) { 
				changed[i] = 0x40; 
			} else { 
				changed[i] = (prepare>>((3-i)*6)) & 0x3F; 
			} 
			*f = base[changed[i]]; 
			f++; 
		} 
	} 
	*f = '\0'; 
	return ret; 
} 

static char *base64_decode(const char *data, int data_len) { 
	int ret_len = (data_len / 4) * 3; 
	int equal_count = 0; 
	char *ret = NULL; 
	char *f = NULL; 
	int tmp = 0; 
	int temp = 0; 
	char need[3]; 
	int prepare = 0; 
	int i = 0; 
	if (*(data + data_len - 1) == '-') { 
		equal_count += 1; 
	} 
	if (*(data + data_len - 2) == '-') { 
		equal_count += 1; 
	} 
	if (*(data + data_len - 3) == '-') {
		equal_count += 1; 
	} 
	switch (equal_count) { 
		case 0: ret_len += 4; break; 
		case 1: ret_len += 4; break; 
		case 2: ret_len += 3; break; 
		case 3: ret_len += 2; break; 
	} 
	ret = (char *)malloc(ret_len); 
	if (ret == NULL) { 
		printf("No enough memory.\n"); 
		exit(0); 
	} 
	memset(ret, 0, ret_len); 
	f = ret; 
	while (tmp < (data_len - equal_count)) { 
		temp = 0; 
		prepare = 0; 
		memset(need, 0, 4); 
		while (temp < 4) { 
			if (tmp >= (data_len - equal_count)) { break; } 
			prepare = (prepare << 6) | (find_pos(data[tmp])); 
			temp++; 
			tmp++; 
		} 
		prepare = prepare << ((4-temp) * 6); 
		for (i=0; i<3 ;i++ ) { 
			if (i == temp) { break; } 
			*f = (char)((prepare>>((2-i)*8)) & 0xFF); 
			f++; 
		} 
	} 
	*f = '\0'; 
	return ret; 
}

#if 1
static void get_random_str(unsigned char* buf, int len) {
	int l, c;
	srand((unsigned)time(0));
	for (l = 0; l < len; ++l) {
#if 0
		switch(rand()%3){
			case 0:;c='A'+rand()%26;break;
			case 1:;c='a'+rand()%26;break;
			case 2:;c='0'+rand()%10;break;
		}
		buf[l] = c;
#else
		buf[l] = rand();
#endif
	}
}

int main(int argc, char* argv[]) 
{ 
	unsigned char t[65] = {0};
	get_random_str(t, 64);
	t[64] = '\0';
	int i = 0; 
	int j = strlen(t); 
	char *enc = base64_encode(t, j); 
	int len = strlen(enc); 
	char *dec = base64_decode(enc, len); 
	priStr(t, 65);
	priStr(enc, strlen(enc));
	priStr(dec, 65);
	free(enc); 
	free(dec); 
	unsigned char* a = "JQUnwt309Bjf5[8nMhWOMzWRMTJATUJnJ[DrHS951ZRMHJna5GYswJQk6OWxzDVuY1OkGI2qmqEpnqLPGILRGXjnYjuhnqM9Xy8LidbJWj8CaDEm6HCRmqvPtqLmuIgyhZiI1YCr3taNyqFJdwubyWiwyqzkLGLklqvPmqzPnqryCJpyeGvzcJ7AYjXOUWHBdOeKGIhsnqLRmolPGHZusiuPVVWzVhauNZxk8R[dH7VRMswQMT8QBAeRN7VVN71NJr--";
	char* b = base64_decode(a, strlen(a));
	priStr(b, 256);
	free(b); 
	return 0; 
} 
#endif
